import java.util.ArrayList;
import java.util.Iterator;
import java.util.Stack;

public class FSP {

	ArrayList<Type> types;
	State init;
	State goal;
	ArrayList<Action> actions;

	public FSP(ArrayList<Type> type, State ini, State goa,
			ArrayList<Action> actio) {
		types = type;
		init = ini;
		goal = goa;
		actions = actio;
	}

	public void run() throws ParserException {
		Stack<State> stany = new Stack<State>();
		stany.add(init);
		long start = System.currentTimeMillis();
		while (!goal(stany.peek())) {
			stany = run(stany);
		}
		long duration = System.currentTimeMillis() - start;
		State win = stany.peek();
		System.out.print(win.done);
		System.out.println(duration);

	}

	private Stack<State> run(Stack<State> stany) throws ParserException {
		State current = stany.peek();
		if (current.possible == null) {
			current.possible = findActions(current);
		}
		if (current.possible.isEmpty() || kolko(stany, current)) {
			stany.pop();
		} else {
			stany.push(current.action());
		}
		return stany;
	}

	private boolean kolko(Stack<State> stany, State current) {
		for (int i = 0; i < stany.size() - 1; i++) {
			if (current.equals(stany.get(i))) {
				return true;
			}
		}
		return false;
	}

	private boolean goal(State s) {
		for (int v : goal.variables.keySet()) {
			if (!s.variables.containsKey(v)) {
				return false;
			}
		}
		return true;
	}

	private Stack<Action> findActions(State st) throws ParserException {
		Stack<Action> wyn = new Stack<Action>();	
		for (Action a : actions) {
			boolean poss = true;
			Iterator<Integer> it = a.pre.variables.keySet().iterator();
			while (poss && it.hasNext())
				if (!st.variables.containsKey(it.next())) {
					poss = false;
				}

			if (poss) {
				wyn.push(a);
			}
		}
		return wyn;
	}

}
